package com.example.dmservice.excelInput.service;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.util.ListUtils;
import com.alibaba.fastjson.JSON;
import com.example.dmcommom.Enum.ElectricityCategoryEnum;
import com.example.dmcommom.Enum.ElectricityTimeCategoryEnum;
import com.example.dmcommom.SpringBeanHelper;
import com.example.dmcommom.StringUtils;
import com.example.dmcommom.TimeUtil;
import com.example.dmdomain.ElectricityTimeSlotRepository;
import com.example.dmdomain.entity.ElectricityTimeSlot;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;

import java.util.*;

/**
 * @author yym
 */
@Slf4j
public class TimeSlotDataListener extends AnalysisEventListener<Map<Integer, String>> {

	private static final int PROVINCE_COL_NUM = 0;
	private static final int ELECTRICITY_CATE_COL_NUM = 1;
	private static final int VOL_COL_NUM = 2;
	private static final int YEAR_COL_NUM = 3;
	private static final int MON_COL_NUM = 4;

	private static final int TIME_SLICE_NUM = 24;

	private static final int BATCH_COUNT = 100;
	private List<ElectricityTimeSlot> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);

	private String currentData ;

	private final Map<String, ElectricityTimeSlot> slotMap = new HashMap<>();

	@Override
	public void invoke(Map<Integer, String> data, AnalysisContext context) {
		if (data.isEmpty()) {
			return;
		}
		if (Strings.isEmpty(JSON.toJSONString(data)) || "{}".equals(JSON.toJSONString(data))) {
			return;
		}
		log.info("解析到一条数据:{}", JSON.toJSONString(data));
		currentData = JSON.toJSONString(data);
		List<ElectricityTimeSlot> dataList = new ArrayList<>();

		List<String> monthList = new ArrayList<>();
		if (!StringUtils.isEmpty(data.get(MON_COL_NUM))) {
			monthList = Arrays.asList(data.get(MON_COL_NUM).split(","));
		} else {
			for (int i = 1; i < 13; i++) {
				monthList.add(String.valueOf(i));
			}
		}

		int num = MON_COL_NUM + 1;

		ElectricityTimeCategoryEnum e = ElectricityTimeCategoryEnum.fromString(data.get(num));
		if (e == null) {
			throw new RuntimeException();
		}

		int st = 0, et = 0, id = 0;
		int st_offset = 0;

		for (int i = num + 1; i < num + TIME_SLICE_NUM + 1; i++) {
			et += 1;
			if (data.get(i) != null && data.get(i).length() > 1) {
				for (String s : monthList) {
					setData(data, s, e, st, st_offset, et, 30, id);
				}
				e = ElectricityTimeCategoryEnum.fromString(String.valueOf(data.get(i).charAt(1)));
				id++;
				st = et;
				st_offset = 30;
			} else if (e != null && !e.equals(ElectricityTimeCategoryEnum.fromString(data.get(i)))) {
				for (String s : monthList) {
					setData(data, s, e, st, st_offset, et, 0, id);
				}
				id++;
				st = et;
				st_offset = 0;
				e = ElectricityTimeCategoryEnum.fromString(data.get(i));
			}
		}

		cachedDataList.addAll(dataList);
		if (cachedDataList.size() >= BATCH_COUNT) {
			saveData();
			cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
		}
	}

	private void setData(Map<Integer, String> data, String s, ElectricityTimeCategoryEnum e, int st, int st_min, int et, int et_min, int id) {
		ElectricityTimeSlot electricityTimeSlot = new ElectricityTimeSlot();
		electricityTimeSlot.setProvince(data.get(PROVINCE_COL_NUM));
		electricityTimeSlot.setCity(data.get(PROVINCE_COL_NUM));
		electricityTimeSlot.setElectricityCategory(ElectricityCategoryEnum.fromString(data.get(ELECTRICITY_CATE_COL_NUM)));
		electricityTimeSlot.setVoltage(data.get(VOL_COL_NUM));
		electricityTimeSlot.setTimeCategory(e);
		electricityTimeSlot.setYear(Integer.parseInt(data.get(YEAR_COL_NUM)));
		electricityTimeSlot.setMonth(Integer.parseInt(s));
		electricityTimeSlot.setStartTime(TimeUtil.getCalenderByHourAndMinute(st, st_min));
		electricityTimeSlot.setEndTime(TimeUtil.getCalenderByHourAndMinute(et, et_min));
		electricityTimeSlot.setId(electricityTimeSlot.getUid(id));
		cachedDataList.add(electricityTimeSlot);
	}

	@Override
	public void doAfterAllAnalysed(AnalysisContext context) {
		saveData();
		slotMap.clear();
		log.info("所有数据解析完成！");
	}

	/**
	 * 加上存储数据库
	 */
	private void saveData() {
		if (cachedDataList.isEmpty()) {
			return;
		}
		log.info("{}条数据，开始存储数据库！", cachedDataList.size());
		ElectricityTimeSlotRepository electricityTimeSlotRepository = SpringBeanHelper.getBean(ElectricityTimeSlotRepository.class);
		if (electricityTimeSlotRepository != null) {
			electricityTimeSlotRepository.saveAll(cachedDataList);
			log.info("存储数据库成功！");
		} else {
			log.error("存储数据库失败!");
		}
	}

	@Override
	public void onException(Exception exception, AnalysisContext context) throws Exception {
		throw new RuntimeException("读取数据异常：" + currentData);
	}
}